var express = require('express');
const bodyParser = require('body-parser')
var app = express();

// 解析json格式请求体中间件(案例中暂时没用到遇到的时候使用此方法)
const jsonParser = bodyParser.json()

// 解析queryString 格式中间件
//const urlencodedParser = bodyParser.urlencoded({ extended: false })

const controllerPackagePath = 'controller'
const user = {userName:'zhangsang',nickName:'张三'}

function buildCtx(req){
    const body = req.body
    let url =req.url
    const index=url.indexOf('?')
    
    if(index>-1){
        url = url.substring(0,index)
    }
    const ctx = {
        method: req.method,
        url,
        query: req.query,
        body: body,
        headers: req.headers,
        user
    }
    return ctx
}


async function callMethod(modulePath,method,args){

    // 这里必须是./ 相对路径定位   如果是 / 绝对路径 加载不到 
    // 绝对路径写法 require('D:\\test\tt.js') 或者 linux require('/data/test/tt.js')
    const md = require('./'+modulePath+'.js')
    
    const fun = md[method]
    let ret = {code:200,msg:'操作成功'}
    if(!fun){
        ret.code = 404
        ret.msg = '方法不存在'+module+' '+method
    }else{
        try{
            const result = fun(...args)
            if(result instanceof Promise){
                ret.data = await result
            }else{
                ret.data = result
            }
        }catch(e){
            ret.code = 500
            let msg = e.message||'出错了'
            if(msg.startsWith('{')){
                try{
                    const ret  = JSON.parse(e.message)
                    const errMsg = ret?.msg
                    if(errMsg){
                        msg = errMsg
                    }
                }catch(e){
                    
                }
            }
            ret.msg = msg
        }
    }
    return ret
}

//这个放前面 不然调用到 '/:controller/:method'去了
app.post('/rpc/call', jsonParser,async function (req, res) {
    const body = req.body
    let modulePath = body.class || body.modulePath
    const method = body.method
    const args = body.args

    modulePath= modulePath.replaceAll('.','/')
    const ret = callMethod(modulePath,method,args)
    if(ret instanceof Promise){
        const awaitRet = await ret
        res.json(awaitRet)
    }else{
        res.json(ret)
    }
    //res.send(JSON.stringify(ret))
})

app.post('/:controller/:method', jsonParser, async function (req, res) {
    let controller = req.params.controller
    const method = req.params.method 

    const subffix = "Controller";//后缀
    if(!controller.endsWith(subffix)){
        controller += subffix
    }
    controller = controller.charAt(0).toUpperCase()+controller.substring(1)
   
    const args = []
    const ctx = buildCtx(req)

    args.push(ctx)

    const modulePath = controllerPackagePath+'/'+controller
    const ret = callMethod(modulePath,method,args)
    if(ret instanceof Promise){
        const awaitRet = await ret
        res.json(awaitRet)
    }else{
        res.json(ret)
    }
    //res.send(JSON.stringify(ret))//JSON.stringify(ctx)
})


  
var server = app.listen(8889, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例，访问地址为 http://%s:%s", host, port)
 
})